home *** CD-ROM | disk | FTP | other *** search
/ Programming Sound Cards / Programming Sound Cards.iso / sound_52 / bendlib.ma < prev    next >
Text File  |  1995-01-01  |  17KB  |  598 lines

  1. #
  2. # bendlib.ma - (dx7) pitch bend library of Ravel routines
  3. #
  4. # Implementation Assumptions:
  5. #
  6. # 1. Setup for dx7 type instrument.
  7. # might work elsewhere as is but may take some changes.
  8. #
  9. # 2. check SEMITONEUNITS; i.e., no of pitch bend
  10. # units per semitone. We set poff to 1.
  11. #
  12. # 3. Assume that
  13. # dx7 is setup as follows:
  14. #    range 12 (an octave span for the bend)
  15. #    step 0 - continuous bend (not semitones)
  16. #
  17. # Functions supported:
  18. ##############################################################
  19. # 1. riff bendUp(firstNote, firstTime, bendTime, totalTime, interval, velocity, vibrattoFlag, vibrattoSteps)
  20. #    pitch bend up of interval of 1-12 semitones
  21. # 2. riff bendDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vibrattoFlag, vibrattoSteps)
  22. #    pitch bend down of interval of 1-12 semitones
  23. # 3. riff bendUpDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vibrattoFlag, vibrattoSteps)
  24. #    pitch bend up then down 
  25. # 4. riff vibratto(note, bendTime, totalTime, vibrattoStep, velocity)
  26. #    vibrato on specified note
  27. #
  28. # There are also some test routines.
  29. # They are at the bottom of the module. They are setup as riffs.
  30. # They can function as examples of how to use the above riffs.
  31.  
  32.  
  33. # bend units per semi-tone 
  34. SEMITONEUNITS = 680
  35. # bend units per whole-tone 
  36. WHOLETONEUNITS = 1360
  37. # bend units at pitchbend center
  38. BENDCENTER = 8192
  39.  
  40. #
  41. # vibratto - play vibratto around requested tone.
  42. #
  43. # time is broken up into two parts, bendTime and remainder.
  44. # bendTime comes first. This permits vibratto followed by
  45. # normal non-vibratto tone.
  46. #
  47. # vibrattoStep - range of bend around center tone.
  48. #    10 - minimum
  49. #    60 - medium
  50. #    100 - heavy
  51. riff vibratto(firstNote, bendTime, totalTime, vibrattoStep, velocity)
  52. # interval - number of semitones to bend up
  53.     int events
  54.     int bendIncrement
  55.     int curincrement
  56.     int bendvalue
  57.     int elapsedTime
  58.     int remainingTime
  59.  
  60.     # make sure pitch bend offset is set at 1 so
  61.     # that we use the true MIDI numbers in decimal
  62.     poff 1
  63.  
  64.     bendIncrement = vibrattoStep
  65.  
  66.     # play note with 0 eventime    
  67.     # the note lasts "totalTime" time before a noteoff
  68.     # is issued
  69.     note firstNote    0,totalTime        velocity
  70.  
  71.     bendvalue = BENDCENTER
  72.     # start off with pitch bend wheel centered
  73.     # take no time to do this
  74.     bend    0    BENDCENTER
  75.  
  76.     # loop through pitch bend up
  77.     elapsedTime = 0
  78.     for ( events = 0; events < bendTime; events++)
  79.         # alternate up/down around pitch
  80.         if ({events % 2} == 0)
  81.             bend 1 BENDCENTER+bendIncrement
  82.         else
  83.             bend 1 BENDCENTER-bendIncrement 
  84.         end
  85.         elapsedTime++
  86.     end
  87.     # issue another pitch bend to make sure we
  88.     # arrived where we want because for loop
  89.     # above may not have arrived precisely
  90.     bend 0    BENDCENTER 
  91.     # use bend constant to return pitchbend wheel to center
  92.     poff 1
  93.     # deterime amount of eventtime remaining
  94.     # we may have some slop if the amount of time
  95.     # spent playing bends did not equal the bendTime
  96.     if (elapsedTime == bendTime)
  97.         remainingTime = totalTime - bendTime
  98.     else
  99.         remainingTime = {bendTime - elapsedTime} + {totalTime - bendTime}
  100.     end
  101.     # tie note for remaining time
  102.     tie  remainingTime
  103. #     void printf("bend %d \n",BENDCENTER)
  104.     # issue rest to make sure noteoff in effect. this
  105.     # is paranoia most likely
  106.     rest 0
  107.     # put pitchbend wheel at center
  108.     bend 0 BENDCENTER
  109. #    void dumptime()
  110. end
  111.  
  112. #
  113. # vnonote - play vibratto around requested tone. Used
  114. #    by other bend routines. Does not issue initial note.
  115. #    Also assumes that we do pitch bend for entire totalTime.
  116. #    I.e., not broken up into pitch bend, no pitch bend step.
  117. #
  118. # vibrattoStep - range of bend around center tone.
  119. #    10 - minimum
  120. #    60 - medium
  121. #    100 - heavy
  122. riff vnonote(firstNote, curbend, totalTime, vibrattoStep, velocity)
  123. # interval - number of semitones to bend up
  124.     int events
  125.     int bendvalue
  126.     int bendIncrement
  127.     int elapsedTime
  128.     int remainingTime
  129.  
  130.     # make sure pitch bend offset is set at 1 so
  131.     # that we use the true MIDI numbers in decimal
  132.     poff 1
  133.  
  134.     bendIncrement = vibrattoStep
  135.  
  136.     bendvalue = curbend
  137.  
  138.     # loop through pitch bend up
  139.     for ( events = 0; events < totalTime; events++)
  140.         # alternate up/down around pitch
  141.         if ({events % 2} == 0)
  142.             bend 1 bendvalue+bendIncrement
  143.         else
  144.             bend 1 bendvalue-bendIncrement 
  145.         end
  146.     end
  147.     # issue another pitch bend to make sure we
  148.     # arrived where we want because for loop
  149.     # above may not have arrived precisely
  150.     bend 0    bendvalue 
  151.     # issue rest to make sure noteoff in effect. this
  152.     # is paranoia most likely
  153.     rest 0
  154. #    void dumptime()
  155.     bend 0 BENDCENTER
  156. end
  157.  
  158. #
  159. # bendUp according to specified interval.
  160. #
  161. # Eventtime is broken up according to following scheme.
  162. #
  163. #    1. issue note for firstTime events
  164. #    2. bend for bendTime events
  165. #    3. tie for remaining time (totalTime - (firstTime + bendTime)
  166. #    Latter non-bend time may have vibratto attached.
  167. #
  168. # e.g.,
  169. #    C, e, e, q, 2, 100, 0, 0 
  170. #
  171. # would mean play C for e events, then bend to D for e events,
  172. # and quit with no vibratto at end.
  173. #
  174. # firstnote - starting note
  175. # firstTime - time devoted to first note before bend
  176. # bendTime - period of time for bends
  177. # totalTime - total elapsed time for note to note. If totalTime
  178. #    is larger than bendTime, we do the pitch bend first
  179. #    and spend the remaining amount of time on the note.
  180. # interval - 1..12 semitones.
  181. # velocity - desired velocity.
  182. # vibratto - flag, 1 for TRUE, 0 for FALSE, if specified
  183. # then we use vibratto for last totalTime-bendTime period.
  184. # This permits more guitar-like effects.
  185. # vibrattoStep - how much pitch bend for vibratto
  186. #
  187. # bendUp(C, 0, h, w, 12, 100, 0, 0)
  188. # would execute a linear bend from C to HC for the first 'h'
  189. # of time, and then execute the HC for the 2nd 'h' with
  190. # total elapsed time of 'w'.
  191. #
  192. # Algorithm needs work but this gets the job done.
  193. #
  194.  
  195. riff bendUp(firstNote, firstTime, bendTime, totalTime, interval, velocity, vflag, vsteps)
  196. # interval - number of semitones to bend up
  197.     int events
  198.     int bendIncrement
  199.     int totalBendUnits
  200.     int pertimeClick
  201.     int curincrement
  202.     int bendvalue
  203.     int elapsedTime
  204.     int remainingTime
  205.  
  206.     # make sure pitch bend offset is set at 1 so
  207.     # that we use the true MIDI numbers in decimal
  208.     poff 1
  209.  
  210.     # don't set interval to 0
  211.     if (interval == 0)
  212.         void printf("bendUp: invalid 0 interval\n")
  213.         final
  214.     end
  215.     # total number of bend units to cover interval
  216.     totalBendUnits = interval * SEMITONEUNITS
  217.  
  218.     # determine per bend event time and how much
  219.     # to bend per bend call
  220.     # if more time than total bend units according
  221.     # to the interval, then divide the time
  222.     # by the number of bend units to get the per
  223.     # bend call time, otherwise time is 1
  224.     if (bendTime > totalBendUnits)
  225.         pertimeClick = bendTime / totalBendUnits
  226.         bendIncrement = totalBendUnits / pertimeClick
  227.     else
  228.         bendIncrement = totalBendUnits / bendTime
  229.         pertimeClick = 1
  230.     end
  231.  
  232. #     void printf("bendIncrement %d\n",bendIncrement)
  233. #     void printf("pertimeClick %d\n",pertimeClick)
  234. #     void printf("totalBendUnits %d\n",totalBendUnits)
  235.  
  236.     # play note with 0 eventime    
  237.     # the note lasts "totalTime" time before a noteoff
  238.     # is issued
  239.     note firstNote    firstTime,totalTime        velocity
  240. #    void dumptime()
  241.     bendvalue = BENDCENTER
  242.     # start off with pitch bend wheel centered
  243.     # take no time to do this
  244.     poff 1
  245.     bend    0    BENDCENTER
  246.     curincrement = bendIncrement
  247.     # loop through pitch bend up
  248.     elapsedTime = 0
  249.     for ( events = 0; events < bendTime; events++)
  250.         bend pertimeClick BENDCENTER+curincrement 
  251. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  252.         curincrement = curincrement + bendIncrement
  253.         elapsedTime = elapsedTime + pertimeClick
  254.     end
  255.     # issue another pitch bend to make sure we
  256.     # arrived where we want because for loop
  257.     # above may not have arrived precisely
  258.     bend 0    BENDCENTER + totalBendUnits
  259.  
  260.  
  261.     # use bend constant to return pitchbend wheel to center
  262.     poff 1
  263.     # deterime amount of eventtime remaining
  264.     # we may have some slop if the amount of time
  265.     # spent playing bends did not equal the bendTime
  266.     if (elapsedTime == bendTime)
  267.         remainingTime = totalTime - {firstTime + bendTime}
  268.     else
  269.         remainingTime = {bendTime - elapsedTime} + {totalTime - {bendTime + firstTime}}
  270.     end
  271.     # do vibratto for last half
  272.     # use special vibratto routine that does not issue note
  273.     # just bends
  274.     if (vflag)
  275.         void vnonote(firstNote, BENDCENTER+totalBendUnits, remainingTime, vsteps, velocity)
  276.         return(0)
  277.     end
  278.     # tie note for remaining time
  279.     tie  remainingTime
  280. #     void printf("bend %d \n",BENDCENTER)
  281.     # issue rest to make sure noteoff in effect. this
  282.     # is paranoia most likely
  283.     rest 0
  284.     # put pitchbend wheel at center
  285.     bend 0 BENDCENTER
  286. #    void dumptime()
  287. end
  288.  
  289. #
  290. # bend Down requested interval
  291. #
  292. # interval 0..12: max range an octave
  293. riff bendDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vflag, vsteps)
  294. # interval - number of semitones to bend up
  295.     int events
  296.     int bendIncrement
  297.     int totalBendUnits
  298.     int pertimeClick
  299.     int curincrement
  300.     int bendvalue
  301.     int elapsedTime
  302.     int remainingTime
  303.  
  304.     # make sure pitch bend offset is set at 1 so
  305.     # that we use the true MIDI numbers in decimal
  306.     poff 1
  307.  
  308.     # don't set interval to 0
  309.     if (interval == 0)
  310.         void printf("bendUp: invalid 0 interval\n")
  311.         final
  312.     end
  313.     # total number of bend units to cover interval
  314.     totalBendUnits = interval * SEMITONEUNITS
  315.  
  316.     # determine per bend event time and how much
  317.     # to bend per bend call
  318.     # if more time than total bend units according
  319.     # to the interval, then divide the time
  320.     # by the number of bend units to get the per
  321.     # bend call time, otherwise time is 1
  322.     if (bendTime > totalBendUnits)
  323.         pertimeClick = bendTime / totalBendUnits
  324.         bendIncrement = totalBendUnits / pertimeClick
  325.     else
  326.         bendIncrement = totalBendUnits / bendTime
  327.         pertimeClick = 1
  328.     end
  329.  
  330. #     void printf("bendIncrement %d\n",bendIncrement)
  331. #     void printf("pertimeClick %d\n",pertimeClick)
  332. #     void printf("totalBendUnits %d\n",totalBendUnits)
  333.  
  334.     # play note with 0 eventime    
  335.     # the note lasts "totalTime" time before a noteoff
  336.     # is issued
  337.     note firstNote    firstTime, totalTime        velocity
  338. #    void dumptime()
  339.     bendvalue = BENDCENTER
  340.     # start off with pitch bend wheel centered
  341.     # take no time to do this
  342.     poff 1
  343.     bend    0    BENDCENTER
  344.     curincrement = bendIncrement
  345.     # loop through pitch bend up
  346.     elapsedTime = 0
  347.     for ( events = 0; events < bendTime; events++)
  348.         bend pertimeClick BENDCENTER-curincrement 
  349. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  350.         curincrement = curincrement + bendIncrement
  351.         elapsedTime = elapsedTime + pertimeClick
  352.     end
  353.     # issue another pitch bend to make sure we
  354.     # arrived where we want because for loop
  355.     # above may not have arrived precisely
  356.     bend 0    BENDCENTER - totalBendUnits
  357. #    void printf("%d \n",BENDCENTER+totalBendUnits)
  358.     # use bend constant to return pitchbend wheel to center
  359.     poff 1
  360.     # deterime amount of eventtime remaining
  361.     # we may have some slop if the amount of time
  362.     # spent playing bends did not equal the bendTime
  363.     if (elapsedTime == bendTime)
  364.         remainingTime = totalTime - {firstTime + bendTime}
  365.     else
  366.         remainingTime = {bendTime - elapsedTime} + {totalTime - {bendTime + firstTime}}
  367.     end
  368.     # do vibratto for last half
  369.     # use special vibratto routine that does not issue note
  370.     # just bends
  371.     if (vflag)
  372.         void vnonote(firstNote, BENDCENTER-totalBendUnits, remainingTime, vsteps, velocity)
  373.         return(0)
  374.     end
  375.     # tie note for remaining time
  376.     tie  remainingTime
  377. #     void printf("bend %d \n",BENDCENTER)
  378.     # issue rest to make sure noteoff in effect. this
  379.     # is paranoia most likely
  380.     rest 0
  381.     # put pitchbend wheel at center
  382.     bend 0 BENDCENTER
  383. #    void dumptime()
  384. end
  385.  
  386. #
  387. # bendUpDown
  388. #
  389. # bend up interval requested
  390. # then bend down
  391. #
  392. riff bendUpDown(firstNote, firstTime, bendTime, totalTime, interval, velocity, vflag, vsteps)
  393. # interval - number of semitones to bend up
  394.     int events
  395.     int bendIncrement
  396.     int totalBendUnits
  397.     int pertimeClick
  398.     int curincrement
  399.     int bendvalue
  400.     int elapsedTime
  401.     int remainingTime
  402.     int firstHalf    # first half of time delta
  403.     int secondHalf    # second half of time delta
  404.  
  405.     # make sure pitch bend offset is set at 1 so
  406.     # that we use the true MIDI numbers in decimal
  407.     poff 1
  408.  
  409.     # don't set interval to 0
  410.     if (interval == 0)
  411.         void printf("bendUp: invalid 0 interval\n")
  412.         final
  413.     end
  414.  
  415.     # split bend timedelta into first half and second
  416.     # half and make sure all events are accounted for
  417.     # in time
  418.     firstHalf = bendTime >> 1
  419.     if ({bendTime % 2} != 0)
  420.         secondHalf = firstHalf + 1
  421.     else
  422.         secondHalf = firstHalf
  423.     end
  424.  
  425.     # total number of bend units to cover interval
  426.     totalBendUnits = interval * SEMITONEUNITS
  427.  
  428.     # determine per bend event time and how much
  429.     # to bend per bend call
  430.     # if more time than total bend units according
  431.     # to the interval, then divide the time
  432.     # by the number of bend units to get the per
  433.     # bend call time, otherwise time is 1
  434.     if (firstHalf > totalBendUnits)
  435.         pertimeClick = firstHalf / totalBendUnits
  436.         bendIncrement = totalBendUnits / pertimeClick
  437.     else
  438.         bendIncrement = totalBendUnits / firstHalf
  439.         pertimeClick = 1
  440.     end
  441.  
  442. #     void printf("bendIncrement %d\n",bendIncrement)
  443. #     void printf("pertimeClick %d\n",pertimeClick)
  444. #     void printf("totalBendUnits %d\n",totalBendUnits)
  445.  
  446.     # play note with 0 eventime    
  447.     # the note lasts "totalTime" time before a noteoff
  448.     # is issued
  449.     note firstNote    firstTime,totalTime        velocity
  450. #    void dumptime()
  451.     bendvalue = BENDCENTER
  452.     # start off with pitch bend wheel centered
  453.     # take no time to do this
  454.     poff 1
  455.     bend    0    BENDCENTER
  456.     curincrement = bendIncrement
  457.     # loop through pitch bend up
  458.     elapsedTime = 0
  459.     for ( events = 0; events < firstHalf; events++)
  460.         bend pertimeClick BENDCENTER+curincrement 
  461. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  462.         curincrement = curincrement + bendIncrement
  463.         elapsedTime = elapsedTime + pertimeClick
  464.     end
  465.  
  466.     # make sure we got to top
  467.     bend 0    BENDCENTER + totalBendUnits
  468.     curincrement = totalBendUnits
  469.  
  470.     # now loop down, keep running totals
  471.     for ( events = 0; events < secondHalf; events++)
  472.         bend pertimeClick BENDCENTER+curincrement
  473. #        void printf("%d %d\n",pertimeClick,BENDCENTER+curincrement)
  474.         curincrement = curincrement - bendIncrement
  475.         elapsedTime = elapsedTime + pertimeClick
  476.     end
  477.  
  478.     # issue another pitch bend to make sure we
  479.     # arrived where we want because for loop
  480.     # above may not have arrived precisely
  481.     bend 0    BENDCENTER 
  482.  
  483. #    void printf("%d \n",BENDCENTER+totalBendUnits)
  484.     # use bend constant to return pitchbend wheel to center
  485.     poff 1
  486.     # deterime amount of eventtime remaining
  487.     # we may have some slop if the amount of time
  488.     # spent playing bends did not equal the bendTime
  489.     if (elapsedTime == bendTime)
  490.         remainingTime = totalTime - {firstTime + bendTime}
  491.     else
  492.         remainingTime = {bendTime - elapsedTime} + {totalTime - {bendTime + firstTime}}
  493.     end
  494.     if (vflag)
  495.         void vnonote(firstNote, BENDCENTER, remainingTime, vsteps, velocity)
  496.         return(0)
  497.     end
  498.  
  499.     # tie note for remaining time
  500.     tie  remainingTime
  501. #     void printf("bend %d \n",BENDCENTER)
  502.     # issue rest to make sure noteoff in effect. this
  503.     # is paranoia most likely
  504.     rest 0
  505.     # put pitchbend wheel at center
  506.     bend 0 BENDCENTER
  507. #    void dumptime()
  508. end
  509.  
  510.  
  511. # should start with 4 note chord from LLC to LC range
  512. # LLC, LE, LG, LC to LC, E, G, HC octave bend. Fun.
  513. # then play major scale via bends twice.
  514. # finish off with normal C to HC for contrast
  515. #
  516. riff testBendUp()
  517.     int i
  518.     void printf("C chord bend up\n")
  519.     LG    0,w
  520.     LE    0,w
  521.     LLC    0,w
  522.     void bendUp(LC, 0, h, w, 12, 100, 0, 0)
  523.     void printf("C scale down twice\n")
  524.     for ( i = 0; i < 2; i++)
  525.         C    q
  526.         # up to D
  527.         void bendUp(C, 0, e, q, 2, 100, 0, 0)
  528.         # up to E
  529.         void bendUp(D, 0, e, q, 2, 100, 0, 0)
  530.         # up to F
  531.         void bendUp(E, 0, e, q, 1, 100, 0, 0)
  532.         void bendUp(F, 0, e, q, 2, 100, 0, 0)
  533.         void bendUp(G, 0, e, q, 2, 100, 0, 0)
  534.         void bendUp(A, 0, e, q, 2, 100, 0, 0)
  535.         void bendUp(B, 0, e, q, 1, 100, 0, 0)
  536.     end
  537.     void printf("C HC reference tones\n")
  538.     C    q
  539.     HC    q
  540.  
  541. end
  542.  
  543. riff testBendDown()
  544.     void printf("bend down: C scale down to G\n")
  545.     # C
  546.     note C    q    127
  547.     # C to LB
  548.     void bendDown(C, 0, e, q, 1, 127, 0, 0)
  549.     # LB to LA
  550.     void bendDown(LB, 0, e, q, 2, 127, 0, 0)
  551.     # LA to LG
  552.     void printf("bend down: LG scale down to LC\n")
  553.     void bendDown(LA, 0, e, q, 2, 127, 0, 0)
  554.     # LG to LC
  555.     void bendDown(LG, 0, e, q, 7, 127, 0, 0)
  556.  
  557.  
  558.     void printf("C then C to LC\n")
  559.     C    q
  560.     void bendDown(C, 0, q, w, 12, 127, 0, 0) 
  561.     #
  562.     void printf("reference tones LC C \n")
  563.     LC    q
  564.     C    q
  565. end
  566.  
  567. riff testVibratto()
  568.     int vsteps
  569.     int i
  570.     vsteps = 0
  571.     for ( i = 0 ; i < 20; i++)
  572.         void printf("vsteps %d\n",vsteps)
  573.         void vibratto(C, q*3, w, vsteps, 100)
  574.         vsteps = vsteps + 10
  575.     end
  576. end
  577.  
  578. riff testguitarRiff()
  579.     void bendUp(LG, 2, e+2, q, 2, 110, 1, 70)
  580.  
  581.     void vibratto(LA, q,q, 80, 100)
  582.     void vibratto(E, q,q, 60, 100)
  583.     void bendUpDown(D, 3, q+e-3, q+e, 2, 110, 0, 0)
  584.     void vibratto(C, e, e, 50, 100)
  585.     void vibratto(LA, 3*q,3*q, 110, 100)
  586.     rest    e
  587.     void bendUp(LG, 0, e, q+e, 2, 110, 1, 110)
  588. end
  589.  
  590. riff testBendLib()
  591.     void testguitarRiff()
  592.     void testBendUp()
  593.     void testBendDown()
  594.     void testVibratto()
  595. end
  596.